package com.dmz.web3;

import org.bouncycastle.util.encoders.Hex;
import org.web3j.abi.TypeEncoder;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Bool;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.abi.datatypes.generated.Bytes32;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.abi.datatypes.generated.Uint8;
import org.web3j.crypto.*;
import org.web3j.utils.Numeric;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.SignatureException;

public class Web3jSignUtil {

    public static String sign(String privateKey,String messageHash){
        Credentials credentials = Credentials.create(privateKey);
        // 对消息哈希进行签名
        byte[] messageHashBytes = Numeric.hexStringToByteArray(messageHash);
        Sign.SignatureData signatureData = Sign.signPrefixedMessage(messageHashBytes, credentials.getEcKeyPair());
        // 将签名数据转换为字符串
        byte[] retval = new byte[65];
        System.arraycopy(signatureData.getR(), 0, retval, 0, 32);
        System.arraycopy(signatureData.getS(), 0, retval, 32, 32);
        System.arraycopy(signatureData.getV(), 0, retval, 64, 1);
        // 签名后的字符串
        return Numeric.toHexString(retval);
    }
    public static boolean verifySign(String signature, String address, String messageHash) {
        try {
            if (address.equalsIgnoreCase(recoverAddress(messageHash, signature))) {
                return true;
            }
        }catch (Exception e){
            return false;
        }
        return false;
    }

    public static String recoverAddress(String messageHash, String signature) throws SignatureException {
        // 将签名数据转换为字节数组
        byte[] signatureBytes = Numeric.hexStringToByteArray(signature);
        // 获取签名数据中的v、r、s值
        byte v = signatureBytes[64];
        byte[] r = new byte[32];
        byte[] s = new byte[32];
        System.arraycopy(signatureBytes, 0, r, 0, 32);
        System.arraycopy(signatureBytes, 32, s, 0, 32);
        // 创建签名对象
        Sign.SignatureData signatureData = new Sign.SignatureData(v, r, s);
        // 恢复地址
        byte[] messageHashBytes = Numeric.hexStringToByteArray(messageHash);
        BigInteger pubKeyRecovered =
                Sign.signedPrefixedMessageToKey(messageHashBytes, signatureData);
        return "0x"+Keys.getAddress(pubKeyRecovered);
    }

    public void createMessageHash(String privKey,Long longValue, String addressValue, BigDecimal bigInteger,Boolean boolVal,Integer intVal){
        Utf8String utf8String = new Utf8String(longValue.toString());
        Address address = new Address(addressValue);
        Uint256 uint256 = new Uint256(bigInteger.toBigInteger());
        Bool bool = new Bool(boolVal);

        StringBuilder msg = new StringBuilder();
        msg.append(Hex.toHexString(utf8String.getValue().getBytes()));
        msg.append(address.getValue().substring(2));
        msg.append(TypeEncoder.encode(uint256));
        msg.append("0").append(intVal.toString());
        msg.append(TypeEncoder.encode(uint256));
        msg.append(address.getValue().substring(2));

        byte[] bytes = Hex.decode(msg.toString());
        byte[] msgHash = Hash.sha3(bytes);
        Bytes32 messageHash = new Bytes32(msgHash);

        ECKeyPair ecKeyPair = ECKeyPair.create(new BigInteger(privKey, 16));
        //Sign.SignatureData signatureData = Sign.signMessage(Sign.getEthereumMessageHash(msgHash), ecKeyPair, true);
        Sign.SignatureData signatureData = Sign.signPrefixedMessage(msgHash, ecKeyPair);

        Uint8 v = new Uint8(signatureData.getV()[0]);
        Bytes32 r = new Bytes32(signatureData.getR());
        Bytes32 s = new Bytes32(signatureData.getS());
    }
}
